home *** CD-ROM | disk | FTP | other *** search
-
-
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
- /* */
- /* This file contains the code for implementing the cScrapItem AE object. */
- /* */
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-
- #include "AEPackObject.h"
- #include "AEObjects.h"
- #include "AERegistry.h"
- #include <packages.h>
- #include "ScriptScrap.h"
- #include "Prototypes.h"
-
-
-
- /* Object from container accessors */
-
- pascal OSErr ItemFromEntryAccessor(DescType desiredClass,
- const AEDesc *container, DescType containerClass, DescType keyForm,
- const AEDesc *keyData, AEDesc *value, long LongInt)
- {
- OSErr err;
- ResType itemType;
- Handle dummyHandle;
-
- /* Since each scrapbook entry is comprised of a set of resources (a/k/a "items", in */
- /* this application's parlance), and the resources aren't kept in any particular */
- /* order, that makes asking for a particular item difficult. We'll support formName */
- /* (where the name is the 4-byte resource type), or a custom form called "type" */
- /* (again the 4 byte type) _only_. */
-
- /* We won't support asking for item 1, item 2 (or first/last/middle) because we */
- /* would have to extend the scrapbook's file format to support such orderings, and */
- /* there's no guarantee our extensions would be valid after the scrapbook DA uses */
- /* the scrapbook file. */
-
- /* Handle 4 character "names" and/or type codes */
- if ((keyForm == formName) || (keyForm == 'type')) {
-
- /* We have a valid key form. Now see if the data is good */
- if ((keyData->descriptorType == typeChar) || (keyData->descriptorType == typeType)) {
-
- /* It's a valid type, so see if the data size is right */
- if (GetHandleSize(keyData->dataHandle) == sizeof(ResType)) {
-
- /* We have the right number of bytes, so extract the data */
- itemType = **(ResType**)(keyData->dataHandle);
-
- /* Make sure that the specified item actually exists */
- SetResLoad(false);
- UseResFile(tokenFRefNum(*container));
- dummyHandle = Get1Resource(itemType, tokenResID(*container));
- SetResLoad(true);
- if (dummyHandle == NULL)
- err = errAENoSuchObject;
- else {
- /* Build a token by duplicating the container and filling in a */
- /* few more fields. */
- err = AEDuplicateDesc(container, value);
- tokenDispatchClass(*value) = cScrapItem;
- tokenFlags(*value) = kObjectToken;
- tokenItemType(*value) = itemType;
- value->descriptorType = cScrapItem;
- }
- }
- else
- err = errAENoSuchObject;
- }
- else
- err = errAENoSuchObject;
- }
- else
- err = errAEBadKeyForm;
-
- return err;
- } /* ItemfromEntryAccessor */
-
-
-
- /* Property from object accessor */
- pascal OSErr PropertyFromItemAccessor ( DescType desiredClass,
- const AEDesc *container, DescType containerClass, DescType keyForm,
- const AEDesc *keyData, AEDesc *returnedToken, long refCon )
- {
- OSErr err = noErr;
- ourToken tokenBody;
- DescType requestedProperty;
-
- /* Copy the container token and change the copy to represent a property. */
- /* The actual reading and writing of the data is done in the token handlers. */
- if ((keyForm != formPropertyID) || (keyData->descriptorType != typeType))
- return errAECantSupplyType;
-
- requestedProperty = **(DescType**)keyData->dataHandle;
-
- /* Check to see if this is a legal property code for this object class */
- if ((requestedProperty != pBestType) && (requestedProperty != pClass)
- && (requestedProperty != pDefaultType))
- return errAECantSupplyType;
-
- /* It's a legal property code, so duplicate the object's token and indicate */
- /* that we want this token to represent a property. */
- err = AEDuplicateDesc(container, returnedToken);
- if (err != noErr) return err;
- tokenFlags(*returnedToken) = kPropToken;
- tokenPropCode(*returnedToken) = requestedProperty;
-
- return noErr;
- } /* PropertyFromEntryAccessor */
-
-
- /* This is the routine that handles creating a new item. Again, since the resources */
- /* aren't stored in any particular order, we're ignoring the "position" parameter. */
- /* If the scrapbook ever supports putting the resources in a specific order, then */
- /* this absolutely should be changed. */
-
- OSErr Item_InsertTokenData (const AERecord *insertionLoc, const AEDescList *data,
- ResType *newTypeCode /* returned */)
- {
- OSErr err = noErr;
- AEDesc objectSpec = {typeNull, NULL};
- AEDesc resolvedToken = {typeNull, NULL};
- short entryNum;
-
- /* Extract and resolve the object specifier */
- err = AEGetKeyDesc(insertionLoc, keyAEObject, typeWildCard, &objectSpec);
- if (err != noErr) goto done;
- if (objectSpec.descriptorType == typeNull)
- return errAENoSuchObject;
- err = AEResolve(&objectSpec, kAEIDoMinimum, &resolvedToken);
- if (err != noErr) goto done;
-
- /* "resolvedToken" represents either the entry's container (the scrapbook) or */
- /* another entry. In either case, the token contains the information necesary */
- /* to access our particular entry in the scrapbook file. */
- if ((resolvedToken.descriptorType != cEntry) && (resolvedToken.descriptorType != cScrapItem)) {
- err = errAETypeError;
- goto done;
- }
-
- UseResFile(tokenFRefNum(resolvedToken));
- entryNum = tokenObjectIndex(resolvedToken);
-
- /* Create the new element and put the data into it */
- err = Put1ScrapbookItem(entryNum, data);
-
- done:
- if (resolvedToken.dataHandle != 0L)
- (void) AEDisposeDesc(&resolvedToken);
- if (objectSpec.dataHandle != 0L)
- (void) AEDisposeDesc(&objectSpec);
- *newTypeCode = data->descriptorType;
- return err;
- } /* Item_InsertTokenData */
-
-
- /* This token handler takes a property or object token and returns the data */
- /* represented by that token in a form which is usable to the outside world. */
-
- OSErr Item_ReadTokenData(const AEDesc *theToken, AEDesc *tokenContents)
- {
- DescType propCode, objClass, typeCode;
- OSErr err = noErr;
-
- /* Get the thing pointed to by a property or object token */
- objClass = tokenDispatchClass(*theToken);
- if (tokenFlags(*theToken) & kPropToken) {
- /* Return any readable properties */
- propCode = tokenPropCode(*theToken);
-
- switch (propCode) {
- case pClass:
- /* Tell the outside world what class this is */
- err = AECreateDesc(typeType, (Ptr)&objClass, sizeof(objClass), tokenContents);
- break;
-
- case pBestType:
- case pDefaultType:
- /* This should be the same as the resource type for the entry */
- typeCode = tokenItemType(*theToken);
- err = AECreateDesc(typeType, (Ptr)&typeCode, sizeof(typeCode), tokenContents);
- break;
- }
- }
-
- else if (tokenFlags(*theToken) & kObjectToken) {
- /* If you're ever asked to "read" an object's value, you should return the */
- /* default type. For us, this is the same as the resource type. */
- UseResFile(tokenFRefNum(*theToken));
- if ((err = ResError()) == noErr)
- err = Get1ScrapbookItem(tokenObjectIndex(*theToken), tokenItemType(*theToken), tokenContents);
- }
- else
- err = errAEEventFailed;
-
- return err;
- }
-
- /* This token handler is used to change the value of some Item */
- OSErr Item_WriteTokenData(const AEDesc *theToken, const AEDesc *data)
- {
- OSErr err;
-
- /* We'll only handle a Set Data request for an Item object, and not */
- /* for any of its properties. */
- if (tokenFlags(*theToken) == kPropToken)
- err = errAENotModifiable;
- else {
- UseResFile(tokenFRefNum(*theToken));
- if ((err = ResError()) == noErr)
- err = Put1ScrapbookItem (tokenObjectIndex(*theToken), data);
- }
- return err;
- }
-
-
- /* This token handler is used to delete a particular object. */
- /* In this implementation, I've decided to make each object */
- /* responsible for its own creation and destruction, so this */
- /* routine will delete a single entry (and all of its */
- /* elements) from the scrapbook. */
- OSErr Item_DeleteTokenData(const AEDesc *theToken)
- {
- OSErr err;
- Boolean elementRemoved;
-
- if (theToken->descriptorType != cScrapItem)
- return errAETypeError;
-
- if (tokenFlags(*theToken) & kPropToken)
- /* Properties may not be deleted */
- return errAENotModifiable;
-
- /* This must be an object token, so get rid of it */
- UseResFile(tokenFRefNum(*theToken));
- if ((err = ResError()) == noErr)
- err = Delete1ScrapbookItem(tokenObjectIndex(*theToken), tokenItemType(*theToken), &elementRemoved);
- if ((err == noErr) && elementRemoved)
- /* If the element was removed, notify the window */
- EntryRemoved(tokenWindow(*theToken), tokenObjectIndex(*theToken));
-
- return err;
- }
-
-
- OSErr Item_GetData(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- return Item_ReadTokenData(token, replyObject);
- } /* Item_GetData */
-
-
- OSErr Item_SetData(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- AEDesc theData;
- OSErr err;
-
- err = AEGetKeyDesc(message, keyAEData, typeWildCard, &theData);
- if (err == noErr) {
- /* We don't handle passing in the data as an object specifier */
- if (theData.descriptorType == typeObjectSpecifier) {
- return errAECantHandleClass;
- }
- err = Item_WriteTokenData(token, &theData);
- (void)AEDisposeDesc(&theData);
- InvalidateWindow(tokenWindow(*token)); /* Make sure the item gets re-drawn */
- }
- return err;
- } /* Item_SetData */
-
-
- OSErr Item_CreateElement(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- OSErr err = noErr;
- AEDesc data = {typeNull, NULL};
- AERecord insertionLoc = {typeNull, NULL};
- ResType newItemType;
-
- /* Extract the insertionLoc record and have the Apple Event Manager coerce it into */
- /* an AERecord for us. */
- err = AEGetParamDesc(message, keyAEInsertHere, typeAERecord, &insertionLoc);
- if (err != noErr) goto done;
-
- /* Extract the optional data */
- err = AEGetParamDesc(message, keyAEData, typeWildCard, &data);
- /* Since this is an optional parameter, don't exit if the keyword wasn't found */
- if ((err != noErr) && (err != errAEDescNotFound)) goto done;
-
- /* Create the element */
- err = Item_InsertTokenData(&insertionLoc, &data, &newItemType);
- if (err != noErr) goto done;
- /* <<< Construct an object specifier for the new entry and return it here */
-
- done:
- if (insertionLoc.dataHandle != 0)
- (void) AEDisposeDesc(&insertionLoc);
-
- if (data.dataHandle != 0)
- (void) AEDisposeDesc(&data);
-
- return err;
- } /* Item_CreateElement */
-
-
- OSErr Item_DeleteElement(AppleEvent *message, AppleEvent *reply, long refcon,
- AEDesc *token, AEDesc *replyObject)
- {
- return Item_DeleteTokenData(token);
- } /* Item_DeleteElement */
-
-
- OSErr Item_AE_Dispatcher(const AppleEvent *message, AppleEvent *reply, long refCon,
- AEEventClass classID, AEEventID eventID,
- const AEDesc *ospec, const AEDesc *token)
- {
- OSErr err = noErr;
- AEDesc replyDesc = {'null', 0L};
-
- if (classID == kAECoreSuite) {
- switch (eventID) {
- case kAECreateElement:
- err = Item_CreateElement(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEDelete:
- err = Item_DeleteElement(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEGetData:
- err = Item_GetData(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEGetDataSize: {
- /* We'll do this one by executing "Get Data" and then returning the */
- /* size of the information. This is not necesarily the most efficient */
- /* way to do things if your returned data is large, but the alternatives. */
- /* are pretty difficult */
- AEDesc tempDesc = {'null', NULL};
- long dataSize;
-
- err = Item_GetData(message, reply, refCon, token, &tempDesc);
- if (tempDesc.dataHandle != NULL) {
- dataSize = GetHandleSize(tempDesc.dataHandle);
- (void)AECreateDesc(typeLongInteger, (Ptr)&dataSize, sizeof(dataSize), &replyDesc);
- (void)AEDisposeDesc(&tempDesc);
- }
- }
- break;
-
- case kAESetData:
- err = Item_SetData(message, reply, refCon, token, &replyDesc);
- break;
-
- case kAEClone:
- case kAECountElements:
- case kAEDoObjectsExist:
- case kAEGetClassInfo:
- case kAEMove:
- default:
- err = errAEEventNotHandled ;
- }
- }
- else
- err = errAEEventNotHandled;
-
- /* See if we need to return anything */
- if ((err == noErr) && (replyDesc.descriptorType != 'null')
- && (reply->descriptorType != 'null')) { /* Note: if the other side didn't ask for a reply, this could be a null desc */
- err = AEPutParamDesc(reply, keyDirectObject, &replyDesc);
- (void)AEDisposeDesc(&replyDesc);
- }
-
- return err;
- } /* Item_AE_Dispatcher */
-
-